home *** CD-ROM | disk | FTP | other *** search
- (* :Title: Supplemental for Plotting Multidimensional Transforms *)
-
- (* :Authors: Brian Evans, James McClellan *)
-
- (*
- :Summary: Plots of m-D magnitude/phase responses
- Generates of m-D pole-zero diagrams and root loci
- *)
-
- (* :Context: SignalProcessing`Support`TransSupport` *)
-
- (* :PackageVersion: 2.7 *)
-
- (*
- :Copyright: Copyright 1989-1991 by Brian L. Evans
- Georgia Tech Research Corporation
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is
- hereby granted, provided that the above copyright notice
- appear in all copies and that both that copyright notice and
- this permission notice appear in supporting documentation,
- and that the name of the Georgia Tech Research Corporation,
- Georgia Tech, or Georgia Institute of Technology not be used
- in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission. Georgia
- Tech makes no representations about the suitability of this
- software for any purpose. It is provided "as is" without
- express or implied warranty.
- *)
-
- (* :History: *)
-
- (* :Keywords: pole-zero diagrams, frequency response *)
-
- (*
- :Source: {Multidimensional Digital Signal Processing}, 1984,
- by D. Dudgeon and R. Mersereau
- *)
-
- (*
- :Warning: The transform objects LTransData and ZTransData must
- be defined before this file is loaded (see "ROC.m").
- *)
-
- (* :Mathematica Version: 1.2 or 2.0 *)
-
- (* :Limitation: *)
-
- (*
- :Discussion: This file has two sections:
-
- A. Magnitude and phase plots (for 2-D signals)
- B. Pole-zero diagrams and root maps (for 2-D transforms)
-
- These sections display the results of transform objects.
- *)
-
- (* :Functions: *)
-
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- Off[ General::spell ];
- Off[ General::spell1 ] ]
-
-
- (* B E G I N P A C K A G E *)
-
- BeginPackage[ "SignalProcessing`Support`MDPlotting`" ]
- EndPackage[]
-
- BeginPackage[ "SignalProcessing`Support`TransSupport`",
- "SignalProcessing`Support`ROC`",
- "SignalProcessing`Support`SigProc`",
- "SignalProcessing`Support`SupCode`" ]
-
-
- Begin["`Private`"]
-
-
- (* A. F R E Q U E N C Y R E S P O N S E *)
-
-
- (* magPhasePlot *)
-
- fmag[w01_Real, omega1_, w02_Real, omega2_, fresp_, logflag_] :=
- Block [ {value},
- value = Abs[ GetValue[fresp, {omega1, omega2}, {w01, w02}] ];
- If [ logflag, 20 Log[10, value], value ] ]
-
- fphase[w01_Real, omega1_, w02_Real, omega2_, fresp_, indegrees_] :=
- Block [ {value},
- value = GetValue[fresp, {omega1, omega2}, {w01, w02}];
- If [ ZeroQ[value], Return[0.] ];
- value = N [ Arg[value] ];
- Chop[ If [ indegrees, value / Degree, value ] ] ]
-
-
- (* Magnitude and phase plots for 2-D signals *)
- magPhasePlot2D[freqresp_, {w1_Symbol, wmin1_, wmax1_},
- {w2_Symbol, wmin2_, wmax2_}, op___] :=
- Block [ {arglist, bogus, degrees, dim1, dim2, fresp, ftemp, logrange,
- magfun, magplot = NullPlot, omega1, omega2, omitplot, options,
- phasefun, phaseplot = NullPlot, plotlabel, plotoptions,
- plotrange, result = 0, rules, w1str, w2str},
-
- (* Check for invalid arguments *)
-
- If [ N[wmin1 > wmax1],
- Message[Plot::limits, {w1, wmin1, wmax1}]; Return[Null] ];
- If [ N[wmin2 > wmax2],
- Message[Plot::limits, {w2, wmin2, wmax2}]; Return[Null] ];
-
- (* Set up for plotting *)
-
- Off[Power::infy, Infinity::indt];
- w1str = StripPackage[w1];
- w2str = StripPackage[w2];
- options = ToList[op] ~Join~ Options[MagPhasePlot];
- plotoptions = RemoveOptions[options, badoptions[MagPhasePlot]];
-
- (* Adjust frequency response so that plot shows periodicity *)
-
- fresp = freqresp /. PeriodicRules;
-
- (* Extract delta functions from the freq. resp. *)
-
- deltafuns = GetDeltaFunctions[funct, {w1, w2}];
- If [ ! SameQ[deltafuns, 0],
- Message[ MagPhasePlot::nodeltas ];
- fresp = fresp //.
- { h_[ c_. Delta[a_. w1 + b_.] ] :> 0,
- h_[ c_. Delta[a_. w1 + b_.] + x_ ] :> h[x],
- Delta[a_. w1 + b_.] :> 0,
- h_[ c_. Delta[a_. w2 + b_.] ] :> 0,
- h_[ c_. Delta[a_. w2 + b_.] + x_ ] :> h[x],
- Delta[a_. w2 + b_.] :> 0 } ];
-
- (* Convert expression to plottable/functional form *)
- (* and replace constants like Pi with numerical value *)
-
- fresp = N [ TheFunction[fresp] ];
-
- (* Find valueless symbols other than frequency variables *)
- (* The first parameter in Summation is a local symbol *)
-
- ftemp = fresp /.
- ( Summation[n_, l_, u_, inc_][expr_] :>
- bogus[l, u, inc, GetVariables[expr /. n -> l]] );
- varlist = Select[GetVariables[ftemp],
- ((! SameQ[#1, w1]) && (! SameQ[#1, w2]))&];
- If [ ! EmptyQ[varlist],
- Message[ MagPhasePlot::unresolved, varlist];
- fresp = fresp /. Map[(#1 -> 1)&, varlist] ];
-
- (* Substitute dummy variables *)
-
- fresp = fresp /. { w1 -> omega1, w2 -> omega2 };
-
- (* Magnitude plotting *)
-
- omitplot = SameQ[Replace[MagRangeScale, options], Null];
- logrange = SameQ[Replace[MagRangeScale, options], Log];
- plotlabel = If [ logrange,
- "Magnitude Response (dB)",
- "Magnitude Response" ];
- plotrange = Replace[PlotRange, options];
-
- If [ ! omitplot,
- arglist = { fmag[w1, omega1, w2, omega2, fresp, logrange],
- { w1, wmin1, wmax1 },
- { w2, wmin2, wmax2 } } ~Join~
- plotoptions ~Join~
- { AxesLabel -> { w1str, w2str, " " },
- DisplayFunction -> disp,
- PlotLabel -> plotlabel,
- PlotRange -> plotrange };
- magplot = Apply[ Plot3D, arglist ] ];
-
- (* Phase plotting *)
-
- omitplot = SameQ[Replace[PhaseRangeScale, options], Null];
- degrees = SameQ[Replace[PhaseRangeScale, options], Degree];
- plotlabel = If [ degrees,
- "Phase Response (degrees)",
- "Phase Response (radians)" ];
-
- If [ ! omitplot,
- arglist = { fphase[w1, omega1, w2, omega2, fresp, degrees],
- { w1, wmin1, wmax1 },
- { w2, wmin2, wmax2 } } ~Join~
- plotoptions ~Join~
- { DisplayFunction -> disp,
- PlotLabel -> plotlabel,
- PlotRange -> All,
- AxesLabel -> { w1str, w2str, " " } };
- phaseplot = Apply[ Plot3D, arglist ] ];
-
- (* Clean up and return the plots as graphics objects *)
-
- On[Power::infy, Infinity::indt];
- { magplot, phaseplot } ]
-
-
- (* B. P O L E - Z E R O P L O T T I N G *)
-
- (* 1. D r i v e r s f o r b o t h z - a n d s - d o m a i n s *)
-
- (* Two-dimensional pole-zero plotting driver *)
- (* -- separable transforms generate two separable pole-zero plots *)
- (* -- symmetric transfer function f only requires one plot *)
- (* -- otherwise, project z1 onto z2 and z2 onto z1 *)
- poleZeroPlot2D[f_, {z1_Symbol, z2_Symbol},
- {rm1_, rm2_}, {rp1_, rp2_}, rest__ ] :=
- Block [ {seplist, z1expr, z2expr},
- If [ SeparableQ[f, {z1, z2}],
- Block [ {poles, seplist, z1expr, z2expr},
- seplist = Separate[f, {z1, z2}];
- z1expr = seplist[[1]];
- z2expr = seplist[[2]];
- poles = PoleZeroPlot[z1expr, z1, rm1, rp1, rest];
- poles = poles ~Join~
- PoleZeroPlot[z2expr, z2, rm2, rp2, rest];
- poles ],
- If [ ! SameQ[f, f /. { z1 -> z2, z2 -> z1 }],
- poleZeroRootMap[f, z2, z1, rm1, rp1, rest] ];
- poleZeroRootMap[f, z1, z2, rm2, rp2, rest] ] ]
-
- PoleZeroRootLocus[ ztrans_, z_Symbol, {w_Symbol, wmin_, wmax_, wstep_},
- ucROCplot_, options_ ] :=
- Block [ {denom, numer, polelist, rmapops, rootmap,
- showops, xlabel, ylabel, zerolist, zstr},
-
- numer = Numerator[ztrans];
- denom = Denominator[ztrans];
-
- (* Tell user what we're doing if Dialogue is enabled *)
-
- If [ InformUserQ[options],
- Print[ " " ];
- Print[ "Numerator polynomial in ", z, ": ",
- numer /. w -> "w" ];
- Print[ "Denominator polynomial in ", z, ": ",
- denom /. w -> "w" ] ];
-
- (* Root map labels and options *)
-
- zstr = StripPackage[z];
- xlabel = "Re " ~StringJoin~ zstr;
- ylabel = "Im " ~StringJoin~ zstr;
- showops = Append[ RemoveOptions[options, {Dialogue}],
- AxesLabel -> { xlabel, ylabel } ];
- rmapops = Prepend[ showops, DisplayFunction :> Identity ];
-
- (* Zero root map *)
-
- If [ ! FreeQ[numer, z],
- rootmap = RootLocus[ numer, z, {w, wmin, wmax, wstep},
- rmapops ][[2]];
- Show[ ucROCplot, rootmap,
- Append[showops, PlotLabel -> "Zero Root Map"] ] ];
-
- (* Pole root map *)
-
- If [ ! FreeQ[denom, z],
- rootmap = RootLocus[ 1/denom, z, {w, wmin, wmax, wstep},
- rmapops ][[2]];
- Show[ ucROCplot, rootmap,
- Append[showops, PlotLabel -> "Pole Root Map"] ] ];
-
- GetRootList[denom, z] ]
-
-
- (* 2. P l o t t i n g r o u t i n e s f o r z - d o m a i n *)
-
- (* Root map two-dimensional pole-zero plotting *)
- (* variable zproj is projected onto z-domain *)
- poleZeroRootMap[f_, zproj_Symbol, z_Symbol, rm_, rp_, True, op___] :=
- Block [ {graphfuns, options, plotstyle,
- rminus, rplus, ucROCplot, w, ztrans},
-
- options = pzOptions[op] ~Join~
- { AspectRatio -> 1, PlotRange -> {{-2, 2}, {-2, 2}} };
-
- (* Make sure that the transform is over common denominator *)
-
- ztrans = Together[f];
- If [ ! MyRationalPolyQ[ztrans, z],
- Message[ PoleZeroPlot::notrational ];
- Message[ PoleZeroPlot::noplot ];
- Return[{}] ];
-
- (* We will plot a unit circle and R- and possibly R+ *)
-
- rminus = N[rm /. zproj -> w];
- rplus = N[rp /. zproj -> w];
-
- plotstyle = { Thickness[0.01] };
- graphfuns = { { Cos[w], Sin[w] } };
-
- If [ ! ZeroQ[rminus],
- PrependTo[ graphfuns, { rminus Cos[w], rminus Sin[w] } ];
- PrependTo[ plotstyle, Dashing[{0.05,0.05}] ] ];
-
- If [ ! InfinityQ[rplus],
- PrependTo[ graphfuns, { rplus Cos[w], rplus Sin[w] } ];
- PrependTo[ plotstyle, Dashing[{0.05,0.05}] ] ];
-
- ucROCplot = Apply[ ParametricPlot,
- { graphfuns,
- {w, 0, 2 Pi},
- AspectRatio -> 1,
- DisplayFunction :> Identity,
- PlotStyle -> plotstyle } ];
-
- (* Project the transfer function and draw the root locus *)
-
- ztrans = ztrans /. zproj -> Exp[I w];
-
- PoleZeroRootLocus[ ztrans, z, {w, 0, 2 Pi, 2 Pi / 20},
- ucROCplot, options ] ]
-
-
- (* 3. P l o t t i n g R o u t i n e s f o r s - d o m a i n *)
-
- (* Root map two-dimensional pole-zero plotting *)
- (* variable sproj is projected onto s-domain *)
- poleZeroRootMap[f_, sproj_Symbol, s_Symbol, rm_, rp_, False, op___] :=
- Block [ {graphfuns, ltrans, options, plotstyle, rminus,
- rplus, ucROCplot, ucROCplot1, ucROCplot2, w},
-
- options = pzOptions[op];
-
- (* Make sure the transfer function is a ratio of two polys *)
-
- ltrans = Together[f];
- If [ ! MyRationalPolyQ[ltrans, s],
- Message[ PoleZeroPlot::notrational ];
- Message[ PoleZeroPlot::noplot ];
- Return[{}] ];
-
- (* We will possibly plot R- and R+ *)
-
- rminusline = NullPlot;
- rplusline = NullPlot;
-
- rminus = N[rm /. sproj -> (I w)];
- rplus = N[rp /. sproj -> (I w)];
-
- plotstyle = { };
- graphfuns = { };
-
- If [ ! InfinityQ[rminus],
- PrependTo[ graphfuns, {rminus, w} ];
- PrependTo[ plotstyle, Dashing[{0.05,0.05}] ] ];
-
- If [ ! InfinityQ[rplus],
- PrependTo[ graphfuns, {rplus, w} ];
- PrependTo[ plotstyle, Dashing[{0.05,0.05}] ] ];
-
- ucROCplot1 = Apply[ ParametricPlot,
- { graphfuns,
- {w, -10, 10},
- DisplayFunction :> Identity,
- PlotStyle -> plotstyle } ];
-
- ucROCplot2 = Apply[ ParametricPlot,
- { graphfuns,
- {w, -10000, 10000},
- DisplayFunction :> Identity,
- PlotStyle -> plotstyle } ];
-
- ucROCplot = Show[ {ucROCplot1, ucROCplot2},
- DisplayFunction :> Identity ];
-
- (* Project the transfer function and draw the root locus *)
-
- ltrans = ltrans /. sproj -> (I w);
-
- PoleZeroRootLocus[ ltrans, s, {w, -10000, 10000, 1000},
- ucROCplot, options ] ]
-
-
- (* E N D P A C K A G E *)
-
- End[]
- EndPackage[]
-
-
- (* E N D I N G M E S S A G E *)
-
- Print["Multidimensional plotting routines for transforms are loaded."]
- Null
-